package yusvr

import (
	"context"
	"net"
	"runtime/debug"

	"gitee.com/yscsky/yu"
	"gitee.com/yscsky/yu/prome"
	"google.golang.org/grpc"
)

// IGrpcServer grpc server接口
type IGrpcServer interface {
	yu.IServer
	grpc.ServiceRegistrar
}

// GrpcServer 封装grpc server
type grpcServer struct {
	*grpc.Server
	name     string
	addr     string
	register func(IGrpcServer)
}

// NewGrpcServer 创建GrpcServer
func NewGrpcServer(name, addr string, reg func(IGrpcServer), opt ...grpc.ServerOption) IGrpcServer {
	return &grpcServer{
		name:     name,
		addr:     addr,
		register: reg,
		Server:   grpc.NewServer(opt...),
	}
}

// OnStart 实现IServer接口
func (gs *grpcServer) OnStart() bool {
	if gs.register == nil {
		yu.Errf("GrpcServer Register is nil")
		return false
	}
	gs.register(gs)
	lis, err := net.Listen("tcp", gs.addr)
	if err != nil {
		yu.LogErr(err, "net.Listen: "+gs.addr)
		return false
	}
	yu.Logf("%s grpc server start at %s", gs.Info(), gs.addr)
	if err = gs.Serve(lis); err != nil {
		yu.LogErr(err, "Serve")
	}
	return true
}

// OnStop 实现IServer接口
func (gs *grpcServer) OnStop() {
	gs.GracefulStop()
}

// Info 实现IServer接口
func (gs *grpcServer) Info() string {
	return gs.name
}

// GrpcRecovery grpc接口panic恢复中间件
func GrpcRecovery() grpc.ServerOption {
	return grpc.UnaryInterceptor(
		func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
			handler grpc.UnaryHandler) (resp interface{}, err error) {
			defer func() {
				if err := recover(); err != nil {
					debug.PrintStack()
				}
			}()
			return handler(ctx, req)
		},
	)
}

// GrpcPrometheus prometheus grpc中间件
func GrpcPrometheus() grpc.ServerOption {
	return grpc.UnaryInterceptor(
		func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
			handler grpc.UnaryHandler) (resp interface{}, err error) {
			defer prome.PromeTrace(info.FullMethod)()
			return handler(ctx, req)
		},
	)
}
